# from const import TYPE_MAP


class StructParser:
    def __init__(self):
        self.state = None
        self.struct_def_str = None
        self.struct_name = None

        self.structs = dict()

    def parse_simple(self, def_str):
        def_tokens = def_str.split()
        mtype = ' '.join(def_tokens[:-1])
        mname = def_tokens[-1]
        if mname.endswith(']'):
            mname, length = mname.split('[')
            length = length[:-1]
            if length.startswith('('):
                length = length[1:-1]
            arr_type = {'type': 'array', 'ele_type': mtype, 'len': length}
            return mname, arr_type
        else:
            return mname.strip(), mtype.strip()

    def parse_struct_def(self, struct_def_str):
        def_strs = []
        cnt_braces = 0
        chars = []
        has_braces = False
        fields = dict()

        # 分离每个field定义
        for c in struct_def_str:
            if c == '{':
                cnt_braces += 1
                has_braces = True
            elif c == '}':
                cnt_braces -= 1
            elif c == ';' and cnt_braces == 0:
                def_strs.append((''.join(chars), has_braces))
                has_braces = False
                chars = []
                continue
            chars.append(c)
    
        for def_str, has_braces in def_strs:
            def_str = def_str.strip()
            if has_braces:
                # 解析嵌套结构, struct or union
                if def_str.startswith('struct'):
                    sub_type = 'struct'
                elif def_str.startswith('union'):
                    sub_type = 'union'
                    
                def_str = def_str.split('{', 1)[-1]
                sub_def_str, sub_name = def_str.rsplit('}', 1)
                sub_name = sub_name.strip()
                if not sub_name and sub_type == 'struct':
                    raise RuntimeError('Struct without a name')

                if not sub_name and sub_type == 'union':
                    # 无名字的 union
                    fields.update(self.parse_struct_def(sub_def_str))
                else:
                    # 有名字的 union or struct
                    fields[sub_name] = {
                        'type': sub_type,
                        'fields': self.parse_struct_def(sub_def_str)
                    }
            else:
                # 解析无嵌套结构
                sub_name, sub_type = self.parse_simple(def_str)
                fields[sub_name] = sub_type

        return fields

    def process_line(self, line):
        if line.startswith('typedef'):
            # typedef A B;
            tokens = line.rstrip(';').split()
            if len(tokens) == 3:
                self.structs[tokens[2]] = self.structs[tokens[1]]
                return

        if line.startswith('typedef struct'):
            # typedef struct _A { ...
            self.state = 'struct_def'
            self.struct_name = line[15:-1].strip()
            if line.endswith('{'):
                self.struct_def_str = ''
            else:
                self.struct_def_str = line.split('{')[-1]
            return

        if self.state == 'struct_def':
            if line == '}' + f' {self.struct_name[1:]}T;':
                # ... } A;
                self.state = None
                sname = line.split('}')[-1].rstrip(';')
                self.structs[sname.strip()] = {
                    'type': 'struct',
                    'fields': self.parse_struct_def(self.struct_def_str)
                }
            else:
                self.struct_def_str += line
            return

    def parse(self, filename):
        with open(filename, 'r') as fin:
            for line in fin:
                line = line.strip()
                self.process_line(line)
